Майнор "Интеллектуальный анализ данных"

Курс "Введение в анализ данных"

Лабораторная работа №2. Кластерный анализ.

Задание 1

В данном задании вам необходимо реализовать алгоритм кластеризации Partition Around Medoids.

Два возможных варианта реализации:

Функция

Нужно написать функцию, которая принимает на вход несколько параметров и возвращает также несколько значений.

Параметры функции:

  • data: данные в виде dataframe или матрицы (аналогично функциям и методам, которые рассматривали на практике);
  • k: число центров (кластеров);
  • metric: расстояние между объектами (те же, что поддерживает функция pdist());
  • max_iter: максимальное число итераций;
  • tol: минимальное значение изменения целевой функции.

Возвращаемые значения:

  • inertia: итоговое значение целевой функции;
  • medoids: центры кластеров - индексы объектов данных, которые являются центрами;
  • labels: метки кластеров для каждого объекта.

Класс

По аналогии с классами в scikit-learn, нужно реализовать класс, наследуемый от Base Estimator.
Подробнее про реализацию своих моделей в scikit-learn: here.

Параметры:

  • k: число центров (кластеров);
  • metric: расстояние между объектами (те же, что поддерживает функция pdist());
  • max_iter: максимальное число итераций;
  • tol: минимальное значение изменения целевой функции.

Методы:

  • fit(): метод для выполнения кластеризации.
    Аргументы метода:
    • data: данные в виде dataframe или матрицы

Атрибуты:

  • inertia_: итоговое значение целевой функции;
  • medoids_: центры кластеров - индексы объектов данных, которые являются центрами;
  • labels_: метки кластеров для каждого объекта.



Note 1: Параметры max_iter и tol должны иметь дефолтные значения.
Note 2: Функции для вычисления расстояний самим реализовывать не нужно, используйте pdist().



Также необходимо написать документацию к функции/методу: описать формат входных данных (параметров) и возвращаемых значений, особенности работы функции и детали реализации алгоритма. В качестве образца можно взять документацию к функциям/методам, которые рассматривали на занятиях.

Наивная реализация алгоритма будет работать довольно медленно - это нормально. Будет плюсом (но не является обязательным), если вы попытаетесь оптимизировать ваш код. Можете указать все ваши решения для оптимизации в документации.

In [256]:
import numpy as np
from sklearn.preprocessing import normalize
import scipy.spatial.distance as dis
from sklearn.decomposition import PCA

def create_medoids(X, k):
    n_samples, n_features = np.shape(X) 
    medoids = np.zeros((k, n_features))
    for i in range(k):
        medoid = X[np.random.choice(range(n_samples))]
        medoids[i] = medoid
        
    non_medoids = []
    for sample in X:
        if not sample in medoids:
            non_medoids.append(sample) 
    return medoids, non_medoids


def assign(X, medoids, k): #присваивает сэмплы к ближайшим медоидам
    clusters = [[] for x in range(k)] 
    for sample_i, sample in enumerate(X):
        closest_i = None
        closest_distance = float("inf")
        for i, medoid in enumerate(medoids):
            distance = dis.euclidean(sample, medoid)
            if distance < closest_distance:
                closest_i = i
                closest_distance = distance
        medoid_i = closest_i
        clusters[medoid_i].append(sample_i)
    return clusters
    
    
def calculate_dist(X, clusters, medoids):
    dist = 0
    for i, cluster in enumerate(clusters):
        medoid = medoids[i]
        for sample_i in cluster:
            dist += dis.euclidean(X[sample_i], medoid)
    return dist


    
def pam(X, k):
    X = [list(x) for x in X.to_numpy()]
    medoids, non_medoids = create_medoids(X, k)
    clusters = assign(X, medoids, k)
    dist = calculate_dist(X, clusters, medoids)
    while True:
        best_medoids = medoids
        lowest_dist = dist
        for medoid in medoids:
            for sample in non_medoids:
                new_medoids = medoids.copy()
                new_medoids[medoids == medoid] = sample
                new_clusters = assign(X, new_medoids, k)
                new_dist = calculate_dist(X, new_clusters, new_medoids)
                if new_dist < lowest_dist:
                    lowest_dist = new_dist
                    best_medoids = new_medoids
        if lowest_dist < dist:
            dist = lowest_dist
            medoids = best_medoids 
        else:
            break
    final_clusters = assign(X, medoids, k)
    
    labels = np.zeros(np.shape(X)[0])
    for cluster_i in range(len(clusters)):
        cluster = clusters[cluster_i]
        for sample_i in cluster:
            labels[sample_i] = cluster_i
                
    return labels

Алгоритм имеет две фазы:

Фаза Build:

  1. Выбрать K объектов в качестве медоид;
  2. Построить матрицу расстояний, если она не была задана;
  3. Отнести каждый объект к ближайшей медоиде;

Фаза Swap:

  1. Для каждого кластера найти объекты, снижающие среднее расстояние, и если такие объекты есть, выбрать те, которые снижают его сильней всего, в качестве медоид;
  2. Если хотя бы одна медоида поменялась, вернуться к шагу 3, иначе завершить алгоритм.

Схема реализации последовательного алгоритма (Псевдокод алгоритма)

1 функция PAM(D, k, tmax=100):

2 # D - матрица расстояний, k - число кластеров, tmax - маскимальное число итераций

3 выполнить фазу BUILD, получить множество метоидов M и множество не-метоидов L

4 вычислить значение целевой функции F

5 для t = 0..tmax-1:

6 выполнить фазу SWAP, вычислить значение целевой функции F'

7 delta = F - F'

8 если delta > 0:

9 обновить множества M и L

10 F = F'

11 иначе:

12 выйти из цикла

13 вернуть М

In [258]:
daata = norm

labels = pam(daata, 6)

labels
Out[258]:
array([1., 3., 0., 4., 2., 1., 1., 4., 1., 0., 3., 2., 0., 1., 0., 0., 4.,
       1., 0., 2., 2., 1., 0., 4., 0., 2., 4., 0., 0., 0., 1., 3., 0., 4.,
       4., 0., 4., 0., 5., 1., 4., 4., 3., 3., 0., 0., 0., 2., 4., 0., 0.,
       1., 3., 1., 4., 1., 0., 4., 4., 2., 0., 0., 4., 0., 3., 0., 3., 1.,
       3., 2., 0., 0., 1., 0., 2., 1., 2., 4., 1., 0., 0., 2., 0., 2., 4.,
       3., 0., 0., 5., 4., 5., 0., 1., 1., 1., 0., 3., 0., 0., 5., 0., 0.,
       1., 0., 1., 0., 3., 2., 4., 2., 1., 1., 4., 2., 3., 1., 0., 2., 0.,
       1., 5., 0., 0., 0., 4., 0., 0., 1., 0., 4., 2., 1., 3., 0., 2., 0.,
       0., 3., 0., 0., 4., 2., 1., 0., 0., 1., 1., 0., 1., 4., 0., 0., 2.,
       4., 1., 4., 1., 4., 4., 2., 0., 3., 0., 1., 4., 1., 0., 3., 0., 0.,
       0., 0., 0., 0., 4., 0., 1., 0., 3., 4., 0., 0., 1., 1., 4., 4., 0.,
       1., 0., 2., 2., 2., 4., 4., 2., 3., 4., 0., 0., 3., 0., 0., 1., 0.,
       4., 0., 3., 0., 4., 4., 4., 2., 3., 2., 0., 3., 3., 3., 2., 0., 2.,
       0., 4., 0., 2., 1., 3., 0., 1., 0., 4., 0., 0., 3., 2., 0., 4., 1.,
       4., 2., 4., 4., 4., 3., 0., 0., 4., 1., 3., 3., 0., 4., 0., 0., 5.,
       4., 0., 2., 0., 5., 1., 2., 0., 4., 3., 3., 1., 2., 3., 3., 3., 3.,
       3., 0., 2., 2., 1., 3., 1., 1., 1., 0., 0., 5., 4., 0., 4., 4., 0.,
       3., 1., 1., 0., 4., 3., 4., 2., 1., 1., 0., 0., 4., 2., 2., 0., 1.,
       4., 0., 0., 0., 0., 0., 0., 2., 0., 0., 1., 2., 1., 0., 0., 1., 2.,
       0., 1., 0., 1., 0., 0.])

Задание 2

В рамках данной лабораторной работы вам предлагается проанализировать набор данных по различным городам США. Каждый город характеризуется следующими признаками:

In [153]:
import pandas as pd
In [154]:
pd.set_option('display.max_rows', 20)
pd.set_option('display.max_colwidth', 100)
In [155]:
data_desc = pd.read_csv('Data_Description.txt', sep=':')
data_desc
Out[155]:
Attribute Description
0 Place City, state (postal code)
1 Climate & Terrain Very hot and very cold months, seasonal temperature variation, heating- and cooling-degree days,...
2 Housing Utility bills, property taxes, mortgage payments.
3 Health Care & Environment Per capita physicians, teaching hospitals, medical schools, cardiac rehabilitation centers, comp...
4 Crime Violent crime rate, property crime rate.
5 Transportation Daily commute, public transportation, Interstate highways, air service, passenger rail service.
6 Education Pupil/teacher ratio in the public K-12 system, effort index in K-12, accademic options in higher...
7 The Arts Museums, fine arts and public radio stations, public television stations, universities offering ...
8 Recreation Good restaurants, public golf courses, certified lanes for tenpin bowling, movie theatres, zoos,...
9 Economics Average household income adjusted for taxes and living costs, income growth, job growth.
10 Longitude Longitude
11 Latitude Latitude
12 Population Population

Notes:

  • Для всех признаков, кроме трех, чем выше значение - тем лучше. Для признаков Housing и Crime - наоборот.
  • Признак Population- статистический признак, не имеющий интерпретации как “лучше-хуже”.
  • Признак Place - уникальный идентификатор объекта (города), он не должен использоваться при кластеризации.
  • Также в данных присутствуют географические координаты городов - Longitude и Latitude. Их также не следует использовать при кластеризации данных.
In [157]:
data = pd.read_csv('Data.txt', sep=' ')
data
Out[157]:
Place Climate HousingCost HlthCare Crime Transp Educ Arts Recreat Econ Long Lat Pop
0 Abilene,TX 521 6200 237 923 4031 2757 996 1405 7633 -99.6890 32.5590 110932
1 Akron,OH 575 8138 1656 886 4883 2438 5564 2632 4350 -81.5180 41.0850 660328
2 Albany,GA 468 7339 618 970 2531 2560 237 859 5250 -84.1580 31.5750 112402
3 Albany-Schenectady-Troy,NY 476 7908 1431 610 6883 3399 4655 1617 5864 -73.7983 42.7327 835880
4 Albuquerque,NM 659 8393 1853 1483 6558 3026 4496 2612 5727 -106.6500 35.0830 419700
... ... ... ... ... ... ... ... ... ... ... ... ... ...
324 Worcester,MA 562 8715 1805 680 3643 3299 1784 910 5040 -71.7950 42.2720 402918
325 Yakima,WA 535 6440 317 1106 3731 2491 996 2140 4986 -120.5130 46.5950 172508
326 York,PA 540 8371 713 440 2267 2903 1022 842 4946 -76.7280 39.9600 381255
327 Youngstown-Warren,OH 570 7021 1097 938 3374 2920 2797 1327 3894 -80.7290 41.1700 531350
328 Yuba-City,CA 608 7875 212 1179 2768 2387 122 918 4694 -121.6220 39.1280 101979

329 rows × 13 columns


Задания:

   0. Выполните необходимую предобработку данных. Перед кластеризацией исключите из данных признаки Place, Long и Lat.

есть

  1. Выполните кластеризацию иерархическим методом.
    Рассмотрите различные расстояния между объектами. Определите, какие следует использовать при кластеризации.
    Выполните кластеризацию с различными расстояниями между кластерами. Сравните результаты, сделайте выводы.

  2. Выполните кластеризацию методом dbscan. Используйте расстояния между объектами, определенные в предыдущем пункте.
    Реализуйте эвристику (см. лекции) для выбора параметров алгоритма. Подберите подходящие параметры алгоритма.

  3. Выполните кластеризацию методом kmeans. Определите наилучшее (на ваш взгляд) число кластеров.

  4. Выполните кластеризацию методом PAM. Используйте расстояния между объектами, определенные в пункте (1). Определите наилучшее (на ваш взгляд) число кластеров.
    Используйте реализацию алгоритма из Задания 1.

  5. (Бонусное) Выполните кластеризацию другими методами. Например, HDBSCAN или алгоритмы, реализованные в scikit-learn.

  6. В результате выполнения предыдущих пунктов вы должны получить 4 или больше разбиения объектов (по одному на каждый метод). Сравните их между собой, сделайте выводы о сходствах и различиях.
    Оцените результаты каждой кластеризации, используя метрики, рассмотренные на занятиях (Silhouette и прочие).

  7. Выберите одно разбиение, наиболее подходящее на ваш взгляд. Предложите интерпретацию полученным кластерам или покажите, что этого сделать нельзя.

  8. Оцените, как полученные кластеры распределены географически. (Бонусное) Провизуализируйте распределение на карте США.
    Оцените, как полученные кластеры распределены по штатам. Можно ли выделить какую-то зависимость (территориальную или для штатов)?

0 задание

In [158]:
norm = data
norm = norm.drop(['Place'], axis=1)
norm = norm.drop(['Long'], axis=1)
norm = norm.drop(['Lat'], axis=1)
norm
Out[158]:
Climate HousingCost HlthCare Crime Transp Educ Arts Recreat Econ Pop
0 521 6200 237 923 4031 2757 996 1405 7633 110932
1 575 8138 1656 886 4883 2438 5564 2632 4350 660328
2 468 7339 618 970 2531 2560 237 859 5250 112402
3 476 7908 1431 610 6883 3399 4655 1617 5864 835880
4 659 8393 1853 1483 6558 3026 4496 2612 5727 419700
... ... ... ... ... ... ... ... ... ... ...
324 562 8715 1805 680 3643 3299 1784 910 5040 402918
325 535 6440 317 1106 3731 2491 996 2140 4986 172508
326 540 8371 713 440 2267 2903 1022 842 4946 381255
327 570 7021 1097 938 3374 2920 2797 1327 3894 531350
328 608 7875 212 1179 2768 2387 122 918 4694 101979

329 rows × 10 columns

In [159]:
from sklearn import preprocessing
In [160]:
names = norm.columns
scaler = preprocessing.StandardScaler()
norm = scaler.fit_transform(norm)
norm = pd.DataFrame(norm, columns=names)
norm
Out[160]:
Climate HousingCost HlthCare Crime Transp Educ Arts Recreat Econ Pop
0 -0.147006 -0.901297 -0.947340 -0.106712 -0.123592 -0.180726 -0.464893 -0.546646 1.946433 -0.460990
1 0.300664 -0.087570 0.469568 -0.210467 0.464411 -1.176652 0.520604 0.974442 -1.085467 0.154950
2 -0.586386 -0.423054 -0.566902 0.025084 -1.158809 -0.795765 -0.628640 -1.223512 -0.254304 -0.459342
3 -0.520064 -0.184142 0.244900 -0.984419 1.844699 1.823613 0.324497 -0.283834 0.312735 0.351765
4 0.997040 0.019500 0.666278 1.463626 1.620402 0.659098 0.290194 0.949648 0.186213 -0.114824
... ... ... ... ... ... ... ... ... ... ...
324 0.192892 0.154701 0.618348 -0.788127 -0.391369 1.511411 -0.294891 -1.160288 -0.448242 -0.133638
325 -0.030943 -0.800525 -0.867458 0.406452 -0.330636 -1.011185 -0.464893 0.364519 -0.498112 -0.391956
326 0.010508 0.010262 -0.472042 -1.461129 -1.341007 0.275089 -0.459284 -1.244586 -0.535052 -0.157925
327 0.259213 -0.556575 -0.088608 -0.064649 -0.577017 0.328164 -0.076347 -0.643341 -1.506590 0.010350
328 0.574240 -0.197998 -0.972303 0.611157 -0.995245 -1.335875 -0.653450 -1.150371 -0.767778 -0.471027

329 rows × 10 columns

1 задание

Посмотрим на различные расстояния между объектами применительно к этим данным

In [151]:
import numpy as np
from scipy.spatial.distance import pdist
In [152]:
import pandas as pd
from matplotlib import pyplot as plt
In [94]:
d = {'euclidean': pdist(norm, 'euclidean'),
     'cityblock': pdist(norm, 'cityblock'),
     'minkowski_6': pdist(norm, 'minkowski', p=6),
     'cosine': pdist(norm, 'cosine'),
     'chebyshev': pdist(norm, 'chebyshev'),
     'canberra': pdist(norm, 'canberra')}
In [95]:
D = pd.DataFrame(d)
D.shape
Out[95]:
(53956, 6)
In [66]:
D.plot(kind="bar",
       subplots=True,
       layout=(3,2),
       sharey=False,
       figsize=(15, 15)
      )
plt.show()

На глаз результаты для всех расстояний выглядят похожими кроме canberra и косинусного. Посчитаем корреляции для более точной оценки.

In [67]:
D_corr = D.corr().loc[['cityblock', 'euclidean', 'minkowski_6', 'chebyshev', 'canberra', 'cosine'],
                      ['cityblock', 'euclidean', 'minkowski_6', 'chebyshev', 'canberra', 'cosine']
                     ]
D_corr
Out[67]:
cityblock euclidean minkowski_6 chebyshev canberra cosine
cityblock 1.000000 0.977341 0.889435 0.854914 0.609345 0.509886
euclidean 0.977341 1.000000 0.961935 0.936928 0.514960 0.500421
minkowski_6 0.889435 0.961935 1.000000 0.995368 0.394962 0.460689
chebyshev 0.854914 0.936928 0.995368 1.000000 0.363405 0.441362
canberra 0.609345 0.514960 0.394962 0.363405 1.000000 0.740167
cosine 0.509886 0.500421 0.460689 0.441362 0.740167 1.000000
In [68]:
import seaborn as sns
In [69]:
plt.figure(figsize=(12, 8))
sns.heatmap(D_corr, annot=True)
plt.show()

Действительно, canberra и косинус сильно отличается от остальных, другие метрики на наших данных оказались очень похожими.

ИЕРАРХИЧЕСКАЯ КЛАСТЕРИЗАЦИЯ

In [70]:
from scipy.cluster.hierarchy import linkage, dendrogram
In [71]:
import matplotlib.pyplot as plt
Z = linkage(norm, method='complete')

plt.figure(figsize=(15, 5))
dendrogram(Z, color_threshold=0)
plt.show()
In [72]:
type(Z)
Out[72]:
numpy.ndarray
In [73]:
Z
Out[73]:
array([[8.20000000e+01, 1.73000000e+02, 5.78305619e-01, 2.00000000e+00],
       [8.00000000e+00, 1.46000000e+02, 6.26357784e-01, 2.00000000e+00],
       [1.42000000e+02, 2.80000000e+02, 6.54690364e-01, 2.00000000e+00],
       ...,
       [6.51000000e+02, 6.53000000e+02, 1.11639962e+01, 3.22000000e+02],
       [2.12000000e+02, 6.48000000e+02, 1.23980041e+01, 7.00000000e+00],
       [6.54000000e+02, 6.55000000e+02, 1.91341807e+01, 3.29000000e+02]])
In [74]:
plt.figure(figsize=(10, 5))
dendrogram(Z, color_threshold=12.5)
plt.axhline(y=12.5, c='k')
plt.show()
In [75]:
plt.figure(figsize=(20, 10))
dendrogram(Z, color_threshold=2.5)
plt.axhline(y=2.5, c='k')
plt.show()
In [76]:
plt.figure(figsize=(20, 10))
dendrogram(Z, color_threshold=7.8)
plt.axhline(y=7.8, c='k')
plt.show()
In [77]:
import numpy as np

def plot_elbow(Z, h=13, w=5):
    plt.figure(figsize=(h, w))
    plt.plot(np.array(range(1, np.shape(Z)[0]+1)), 
             Z[:,2][::-1], 
             marker='o')
    plt.xlabel("Number of clusters")
    plt.ylabel("Merge distance")
    plt.show()
    
plot_elbow(Z)

Оценка динамики изменения расстояний.

Выбираем ту точку, в которой снижение графика замедляется сильнее всего - "сгиб локтя". На графике это примерно 6 кластеров.

После того, как определились с порогом и числом кластеров, нужно извлечь полученное разбиение. Для этого используем функцию fcluster(). Функция возвращает массив длины 𝑛 , содержащий для каждого объекта i номер его кластера.

In [78]:
from scipy.cluster.hierarchy import fcluster
In [79]:
# По числу кластеров
fcluster(Z, t = 6, criterion='maxclust')
Out[79]:
array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 4, 1, 1, 1, 1, 4, 1, 1,
       1, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1,
       1, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 5, 1,
       1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 4, 4, 1, 1, 1, 1, 1, 4, 1, 5, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1,
       3, 1, 4, 1, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 1, 1, 4, 4, 1,
       1, 4, 1, 1, 1, 1, 1, 1, 4, 1, 1, 4, 1, 4, 6, 4, 1, 4, 3, 3, 1, 1,
       1, 1, 1, 4, 1, 1, 3, 1, 1, 1, 1, 1, 1, 5, 1, 1, 4, 1, 1, 4, 1, 1,
       4, 1, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 1, 4, 1, 4,
       3, 1, 1, 1, 3, 2, 3, 3, 3, 4, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 1, 3,
       1, 1, 1, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
      dtype=int32)
In [80]:
# По порогу (высоте дерева)
fcluster(Z, t = 7.8, criterion='distance')
Out[80]:
array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 4, 1, 1, 1, 1, 4, 1, 1,
       1, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1,
       1, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 5, 1,
       1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 4, 4, 1, 1, 1, 1, 1, 4, 1, 5, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1,
       3, 1, 4, 1, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 1, 1, 4, 4, 1,
       1, 4, 1, 1, 1, 1, 1, 1, 4, 1, 1, 4, 1, 4, 6, 4, 1, 4, 3, 3, 1, 1,
       1, 1, 1, 4, 1, 1, 3, 1, 1, 1, 1, 1, 1, 5, 1, 1, 4, 1, 1, 4, 1, 1,
       4, 1, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 1, 4, 1, 4,
       3, 1, 1, 1, 3, 2, 3, 3, 3, 4, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 1, 3,
       1, 1, 1, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
      dtype=int32)

Теперь можно проверить, удалось ли нам получить разбиение

In [296]:
import seaborn as sns

data['cluster'] = fcluster(Z, t = 7.8, criterion='distance')
sns.pairplot(data, hue='cluster', plot_kws={'alpha':0.5}, vars=['Climate', 
                                                                'HousingCost',
                                                                'HlthCare',
                                                                'Crime',
                                                                'Transp',
                                                                'Educ',
                                                                'Arts',
                                                                'Recreat',
                                                                'Econ',
                                                                'Pop'])
plt.show()

В рассмотренном примере мы использовали Евклидово расстояние между объектами. Как мы увидели в начале анализа, расстояния Минковского, Чебышева и Манхеттенских кварталов почти идеально коррелируют с Евклидовым, и разумно ожидать аналогичных результатов кластеризации при их использовании.

Canberra очень сильно отличается от остальных. Давайте посмотрим, что получится при его использовании.

In [81]:
Z = linkage(norm, method='complete', metric='canberra')

plt.figure(figsize=(10, 10))
dendrogram(Z, color_threshold=9.5)
plt.axhline(y=9.5, c='k')
plt.show()

Косинусное расстояние:

In [82]:
Z = linkage(norm, method='complete', metric='cosine')

plt.figure(figsize=(10, 10))
dendrogram(Z, color_threshold=1.6)
plt.axhline(y=1.6, c='k')
plt.show()

2 задание

In [96]:
from sklearn.cluster import DBSCAN
In [97]:
cl_dbscan = DBSCAN(eps=0.185, min_samples=4, metric='cosine')
cl_dbscan.fit(norm)
Out[97]:
DBSCAN(algorithm='auto', eps=0.185, leaf_size=30, metric='cosine',
       metric_params=None, min_samples=4, n_jobs=None, p=None)
In [98]:
np.shape(cl_dbscan.labels_)
Out[98]:
(329,)

Посмотрим на то, как распределились объекты на корневые, пограничные и выбросы. Видно, что почти все объекты оказались корневыми, т.е. плотность объектов довольно высокая при выбранных параметрах.

In [99]:
data['points'] = 'Reachable'
data.iloc[cl_dbscan.core_sample_indices_, 4] = 'Core'
data.loc[cl_dbscan.labels_ == -1, 'points'] = 'Outlier'
In [100]:
sns.pairplot(x_vars="Long", 
             y_vars="Lat", 
             hue='points',
             data=data, 
             height=10)
plt.show()

Посмотрим теперь на результаты кластеризации. Мы получили 6 кластеров и много выбросов. В целом полученная кластеризация выглядит разумно. Скопление объектов слева разделяется на несколько кластеров из-за сильного разброса по глубине эпицентра.

In [101]:
pd.Series(cl_dbscan.labels_).value_counts()
Out[101]:
 0    174
-1     83
 2     47
 1     13
 4      6
 3      6
dtype: int64
In [102]:
data['cl_dbscan'] = cl_dbscan.labels_

sns.pairplot(x_vars="Long", 
             y_vars="Lat", 
             hue='cl_dbscan',
             data=data, 
             height=10)
plt.show()
In [119]:
sns.pairplot(x_vars='cl_dbscan', 
             y_vars=['Climate', 'HousingCost', 'HlthCare', 'Transp', 'Educ', 'Arts', 'Recreat', 'Econ', 'Pop'],
             data=data, 
             height=5,
             plot_kws={'alpha':0.15})
plt.show()

Эвристика для выбора параметром

  1. Выберите MinPts (обычно используются значения от 3 до 9).
  2. Вычислите среднее расстояние по MinPts ближайшим соседям для каждой точки.
  3. Сортируем полученные значения по возрастанию и выводим на экран.
  4. Глядя на график, следует выбрать значение Eps из полосы, где происходит самый сильный перегиб. Чем больше Eps, тем больше получатся кластеры, и тем меньше их будет.
In [120]:
from sklearn.neighbors import NearestNeighbors
neigh = NearestNeighbors(n_neighbors=2)
nbrs = neigh.fit(norm)
distances, indices = nbrs.kneighbors(norm)
distances = np.sort(distances, axis=0)
distances = distances[:,1]
plt.plot(distances)
Out[120]:
[<matplotlib.lines.Line2D at 0x2c892f5d0>]
In [121]:
cl_dbscan = DBSCAN(eps=3, min_samples=227)
cl_dbscan.fit(norm)
Out[121]:
DBSCAN(algorithm='auto', eps=3, leaf_size=30, metric='euclidean',
       metric_params=None, min_samples=227, n_jobs=None, p=None)
In [122]:
data['points'] = 'Reachable'
data.iloc[cl_dbscan.core_sample_indices_, 4] = 'Core'
data.loc[cl_dbscan.labels_ == -1, 'points'] = 'Outlier'
In [123]:
sns.pairplot(x_vars="Long", 
             y_vars="Lat", 
             hue='points',
             data=data, 
             height=10)
plt.show()
In [124]:
pd.Series(cl_dbscan.labels_).value_counts()
Out[124]:
 0    227
-1    102
dtype: int64
In [125]:
data['cl_dbscan'] = cl_dbscan.labels_

sns.pairplot(x_vars="Long", 
             y_vars="Lat", 
             hue='cl_dbscan',
             data=data, 
             height=10)
plt.show()

У меня не получилось евклидовым, какое значение соседей я бы не выбрала(

3 задание

In [161]:
from sklearn.cluster import KMeans
In [162]:
data
Out[162]:
Place Climate HousingCost HlthCare Crime Transp Educ Arts Recreat Econ Long Lat Pop
0 Abilene,TX 521 6200 237 923 4031 2757 996 1405 7633 -99.6890 32.5590 110932
1 Akron,OH 575 8138 1656 886 4883 2438 5564 2632 4350 -81.5180 41.0850 660328
2 Albany,GA 468 7339 618 970 2531 2560 237 859 5250 -84.1580 31.5750 112402
3 Albany-Schenectady-Troy,NY 476 7908 1431 610 6883 3399 4655 1617 5864 -73.7983 42.7327 835880
4 Albuquerque,NM 659 8393 1853 1483 6558 3026 4496 2612 5727 -106.6500 35.0830 419700
... ... ... ... ... ... ... ... ... ... ... ... ... ...
324 Worcester,MA 562 8715 1805 680 3643 3299 1784 910 5040 -71.7950 42.2720 402918
325 Yakima,WA 535 6440 317 1106 3731 2491 996 2140 4986 -120.5130 46.5950 172508
326 York,PA 540 8371 713 440 2267 2903 1022 842 4946 -76.7280 39.9600 381255
327 Youngstown-Warren,OH 570 7021 1097 938 3374 2920 2797 1327 3894 -80.7290 41.1700 531350
328 Yuba-City,CA 608 7875 212 1179 2768 2387 122 918 4694 -121.6220 39.1280 101979

329 rows × 13 columns

In [163]:
norm
Out[163]:
Climate HousingCost HlthCare Crime Transp Educ Arts Recreat Econ Pop
0 -0.147006 -0.901297 -0.947340 -0.106712 -0.123592 -0.180726 -0.464893 -0.546646 1.946433 -0.460990
1 0.300664 -0.087570 0.469568 -0.210467 0.464411 -1.176652 0.520604 0.974442 -1.085467 0.154950
2 -0.586386 -0.423054 -0.566902 0.025084 -1.158809 -0.795765 -0.628640 -1.223512 -0.254304 -0.459342
3 -0.520064 -0.184142 0.244900 -0.984419 1.844699 1.823613 0.324497 -0.283834 0.312735 0.351765
4 0.997040 0.019500 0.666278 1.463626 1.620402 0.659098 0.290194 0.949648 0.186213 -0.114824
... ... ... ... ... ... ... ... ... ... ...
324 0.192892 0.154701 0.618348 -0.788127 -0.391369 1.511411 -0.294891 -1.160288 -0.448242 -0.133638
325 -0.030943 -0.800525 -0.867458 0.406452 -0.330636 -1.011185 -0.464893 0.364519 -0.498112 -0.391956
326 0.010508 0.010262 -0.472042 -1.461129 -1.341007 0.275089 -0.459284 -1.244586 -0.535052 -0.157925
327 0.259213 -0.556575 -0.088608 -0.064649 -0.577017 0.328164 -0.076347 -0.643341 -1.506590 0.010350
328 0.574240 -0.197998 -0.972303 0.611157 -0.995245 -1.335875 -0.653450 -1.150371 -0.767778 -0.471027

329 rows × 10 columns

In [164]:
Z = KMeans(n_clusters = 6, # число кластеров
           init = 'random',
           n_init = 1,
           max_iter = 100, 
           random_state=15434,
          )
Z.fit(norm)
Out[164]:
KMeans(algorithm='auto', copy_x=True, init='random', max_iter=100, n_clusters=6,
       n_init=1, n_jobs=None, precompute_distances='auto', random_state=15434,
       tol=0.0001, verbose=0)
In [165]:
# координты центров кластеров
Z.cluster_centers_
Out[165]:
array([[-0.14839926, -0.50958765, -0.46701541, -0.55029035, -0.73332057,
        -0.46868705, -0.44441806, -0.53565591, -0.61546009, -0.38217066],
       [ 0.50499298,  1.00688356,  2.98491283,  1.23962232,  1.58443372,
         1.58505366,  2.965286  ,  0.93294881,  0.24080929,  3.20908799],
       [-0.12992617, -0.21149499,  0.02275792, -0.1738772 ,  0.72771311,
         0.35227466, -0.08849059, -0.1444223 , -0.25062061, -0.13962539],
       [-0.4445014 , -0.12286722, -0.47840925,  0.74336697, -0.33059055,
        -0.25877687, -0.27108516,  0.24032722,  1.13661642, -0.22137826],
       [ 1.00744688,  1.4540764 ,  0.72019799,  0.27083738,  0.39588067,
         0.38748206,  0.57956505,  0.9739405 ,  0.26899557,  0.35918285],
       [-0.1884569 ,  0.11565196, -0.86196586,  0.3840187 ,  0.74460917,
        -1.4186087 , -0.44137777, -0.28259441,  3.98555502, -0.43239969]])
In [166]:
# метки кластеров для каждого объекта
Z.labels_
Out[166]:
array([3, 2, 0, 2, 4, 0, 0, 2, 0, 2, 4, 3, 0, 0, 4, 0, 0, 2, 0, 1, 3, 0,
       0, 3, 3, 1, 2, 3, 0, 3, 0, 0, 0, 4, 2, 0, 2, 2, 0, 0, 2, 2, 1, 4,
       3, 0, 0, 4, 0, 3, 0, 3, 4, 0, 2, 0, 3, 2, 2, 2, 2, 2, 2, 0, 1, 2,
       4, 0, 1, 3, 0, 2, 0, 2, 3, 0, 1, 4, 0, 2, 2, 3, 0, 4, 2, 1, 0, 0,
       2, 2, 0, 0, 0, 0, 3, 2, 4, 0, 0, 2, 2, 0, 0, 2, 0, 2, 3, 3, 3, 3,
       0, 0, 2, 3, 3, 0, 3, 4, 2, 0, 2, 0, 0, 0, 0, 2, 2, 0, 0, 2, 4, 0,
       4, 0, 1, 0, 0, 2, 0, 0, 2, 2, 0, 0, 2, 0, 0, 2, 0, 2, 0, 2, 2, 2,
       0, 2, 0, 2, 2, 5, 3, 4, 3, 2, 2, 0, 3, 3, 0, 3, 3, 0, 2, 0, 2, 2,
       3, 0, 1, 2, 3, 3, 2, 0, 2, 3, 0, 0, 0, 3, 2, 4, 4, 2, 5, 4, 1, 3,
       0, 4, 0, 0, 0, 0, 3, 2, 4, 0, 2, 4, 2, 4, 1, 1, 2, 4, 4, 4, 3, 3,
       3, 0, 2, 2, 3, 0, 4, 3, 0, 0, 2, 3, 0, 1, 4, 0, 1, 2, 2, 4, 3, 3,
       4, 0, 0, 0, 4, 0, 2, 4, 0, 2, 4, 0, 0, 4, 0, 4, 0, 0, 0, 1, 2, 4,
       4, 4, 3, 3, 4, 1, 4, 4, 4, 4, 3, 3, 2, 4, 0, 0, 0, 3, 0, 2, 2, 2,
       2, 2, 0, 4, 0, 0, 3, 2, 4, 3, 3, 0, 0, 2, 2, 4, 3, 3, 0, 3, 2, 4,
       0, 3, 0, 3, 3, 1, 0, 0, 0, 3, 0, 3, 3, 0, 2, 3, 2, 0, 0, 0, 0],
      dtype=int32)
In [167]:
# Значение целевой функции: сумма квадратов расстояний от объекта до центра кластера, 
#                           к которому он принаджлежит
Z.inertia_
Out[167]:
1828.1785389436106

Добавим к данным координаты центров калстеров, чтобы отобразить их на графике. Чтобы не изменять исходные данные, создадим копию данных и будем работать с ней.

In [168]:
import numpy as np
data_kmeans = norm.copy()

centers = np.zeros((6, 10))
centers[:, 0:10] = Z.cluster_centers_
centers = pd.DataFrame(centers, columns=data_kmeans.columns)

data_kmeans['cluster'] = Z.labels_.astype(str)

centers['cluster'] = np.array(['c0', 'c1', 'c2', 'c3', 'c4', 'c5']).astype(str)

centers
Out[168]:
Climate HousingCost HlthCare Crime Transp Educ Arts Recreat Econ Pop cluster
0 -0.148399 -0.509588 -0.467015 -0.550290 -0.733321 -0.468687 -0.444418 -0.535656 -0.615460 -0.382171 c0
1 0.504993 1.006884 2.984913 1.239622 1.584434 1.585054 2.965286 0.932949 0.240809 3.209088 c1
2 -0.129926 -0.211495 0.022758 -0.173877 0.727713 0.352275 -0.088491 -0.144422 -0.250621 -0.139625 c2
3 -0.444501 -0.122867 -0.478409 0.743367 -0.330591 -0.258777 -0.271085 0.240327 1.136616 -0.221378 c3
4 1.007447 1.454076 0.720198 0.270837 0.395881 0.387482 0.579565 0.973940 0.268996 0.359183 c4
5 -0.188457 0.115652 -0.861966 0.384019 0.744609 -1.418609 -0.441378 -0.282594 3.985555 -0.432400 c5
In [169]:
data_kmeans = data_kmeans.append(centers, ignore_index=True)
data_kmeans.head(20)
Out[169]:
Climate HousingCost HlthCare Crime Transp Educ Arts Recreat Econ Pop cluster
0 -0.147006 -0.901297 -0.947340 -0.106712 -0.123592 -0.180726 -0.464893 -0.546646 1.946433 -0.460990 3
1 0.300664 -0.087570 0.469568 -0.210467 0.464411 -1.176652 0.520604 0.974442 -1.085467 0.154950 2
2 -0.586386 -0.423054 -0.566902 0.025084 -1.158809 -0.795765 -0.628640 -1.223512 -0.254304 -0.459342 0
3 -0.520064 -0.184142 0.244900 -0.984419 1.844699 1.823613 0.324497 -0.283834 0.312735 0.351765 2
4 0.997040 0.019500 0.666278 1.463626 1.620402 0.659098 0.290194 0.949648 0.186213 -0.114824 4
5 -0.155296 -1.061271 -0.544934 -0.656331 -1.218852 0.490509 -0.607713 -1.026403 -0.250609 -0.433691 0
6 0.168021 -0.024588 -0.563906 -1.253620 -0.917259 1.027497 -0.176450 -0.903674 -0.395601 0.127093 0
7 -0.014363 -0.780791 -0.220413 -0.715218 0.527904 0.406214 -0.358965 -0.701606 0.249012 -0.284641 2
8 0.184602 -0.905075 -0.752627 -1.576100 0.024789 -0.115164 -0.624540 -0.788384 -1.196289 -0.432189 0
9 0.582531 -0.756018 -0.515977 0.313914 0.477523 0.115866 -0.413332 -0.913592 0.660900 -0.390621 2
10 2.870623 3.233258 0.838024 0.061538 -0.176734 0.087768 0.535274 1.624034 0.641506 1.581443 4
11 -2.849607 1.607484 -0.583876 0.734541 0.607961 -1.251580 -0.173645 1.430644 1.978756 -0.389800 3
12 -0.072394 -1.109557 -0.604846 -0.232900 -0.928301 -1.079869 -0.587002 -1.249545 -1.990512 -0.429146 0
13 0.433307 -1.100739 -0.365199 0.039105 -1.037344 -0.133896 -0.643310 -1.528473 -1.166737 -0.435986 0
14 0.060249 1.120004 1.320312 0.297089 -0.536299 1.658146 0.951004 0.547992 -0.873982 -0.288544 4
15 0.176311 -1.182616 -0.586872 0.459731 -0.799934 -1.954036 -0.621952 -0.844170 -0.734531 -0.451092 0
16 -1.183280 -0.197158 -0.352219 -1.222774 -0.629468 0.090890 -0.428218 0.581463 -0.231216 -0.258698 0
17 1.287197 -0.682119 0.018234 -1.107803 0.604510 0.546705 -0.379676 -0.376810 -0.304173 -0.404932 2
18 0.516209 -0.695136 -0.579882 -0.078670 -1.617755 -0.527271 0.085242 -1.047477 -0.306944 -0.439596 0
19 1.303777 -0.012831 2.006299 0.972896 2.897860 0.755881 0.951004 -0.599953 0.729240 1.811859 1
In [135]:
sns.pairplot(data_kmeans.sort_values('cluster'), 
             hue='cluster', 
             plot_kws={'alpha':0.5}, 
             vars=['Climate', 'HousingCost', 'HlthCare', 'Crime', 'Transp',
                        'Educ', 'Arts', 'Recreat', 'Econ', 'Pop']
            )
plt.show()
/opt/anaconda3/lib/python3.7/site-packages/numpy/core/_methods.py:217: RuntimeWarning: Degrees of freedom <= 0 for slice
  keepdims=keepdims)
/opt/anaconda3/lib/python3.7/site-packages/numpy/core/_methods.py:209: RuntimeWarning: invalid value encountered in double_scalars
  ret = ret.dtype.type(ret / rcount)
In [136]:
inertia = []
for k in range(1, norm.shape[0]+1):
    Z = KMeans(n_clusters=k, 
               init = 'random',
               n_init = 100,
               max_iter = 1000).fit(norm)
    inertia.append(Z.inertia_)

plt.plot(range(1, data.shape[0]+1), inertia, 'bo-', marker='s')
plt.xlabel('$k$')
plt.ylabel('Objective function value')
plt.axvline(x=23, c='r')
plt.show()
In [137]:
inertia = np.sqrt(inertia)
In [138]:
plt.plot(range(1, norm.shape[0]+1), inertia, 'bo-', marker='s')
plt.xlabel('$k$')
plt.ylabel('$J(C_k)$')
plt.axvline(x=6, c='r')
plt.show()

При таких данных достаточно сложно определить точное количнство кластеров, я остановилась на 6

4 задание

In [260]:
data_pam['cluster_Pam'] = pam(norm, 6)
plt.scatter(norm.to_numpy()[:, 0], norm.to_numpy()[:, 1], 
            c = [int(x) for x in data_pam['cluster_Pam'].to_numpy()], 
            s = 50, cmap = 'viridis')
Out[260]:
<matplotlib.collections.PathCollection at 0x1e5a19c50>

5 задание

In [2]:
!pip install hdbscan
Collecting hdbscan
  Downloading hdbscan-0.8.26.tar.gz (4.7 MB)
     |████████████████████████████████| 4.7 MB 5.9 MB/s eta 0:00:01
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
    Preparing wheel metadata ... done
Requirement already satisfied: joblib in /opt/anaconda3/lib/python3.7/site-packages (from hdbscan) (0.13.2)
Requirement already satisfied: numpy>=1.16.0 in /opt/anaconda3/lib/python3.7/site-packages (from hdbscan) (1.17.2)
Requirement already satisfied: scipy>=0.9 in /opt/anaconda3/lib/python3.7/site-packages (from hdbscan) (1.4.1)
Requirement already satisfied: six in /opt/anaconda3/lib/python3.7/site-packages (from hdbscan) (1.12.0)
Requirement already satisfied: scikit-learn>=0.17 in /opt/anaconda3/lib/python3.7/site-packages (from hdbscan) (0.21.3)
Requirement already satisfied: cython>=0.27 in /opt/anaconda3/lib/python3.7/site-packages (from hdbscan) (0.29.13)
Building wheels for collected packages: hdbscan
  Building wheel for hdbscan (PEP 517) ... done
  Created wheel for hdbscan: filename="hdbscan-0.8.26-cp37-cp37m-macosx_10_9_x86_64.whl size=734613 sha256=c4deb11e78e3d992721e3bdaba7a9b7d8f4bf9b786b90797a36901c6e1fda203
  Stored in directory: /Users/macbookbro/Library/Caches/pip/wheels/12/bb/54/7401fdc7883b5975dba5514a185d75d7a0986472df4957637b
Successfully built hdbscan
Installing collected packages: hdbscan
Successfully installed hdbscan-0.8.26
In [139]:
import hdbscan
In [140]:
cl_hdbscan = hdbscan.HDBSCAN(min_cluster_size=2, gen_min_span_tree=True)
cl_hdbscan.fit(norm)
Out[140]:
HDBSCAN(algorithm='best', allow_single_cluster=False, alpha=1.0,
        approx_min_span_tree=True, cluster_selection_epsilon=0.0,
        cluster_selection_method='eom', core_dist_n_jobs=4,
        gen_min_span_tree=True, leaf_size=40,
        match_reference_implementation=False, memory=Memory(location=None),
        metric='euclidean', min_cluster_size=2, min_samples=None, p=None,
        prediction_data=False)
In [141]:
pd.Series(cl_hdbscan.labels_).value_counts()
Out[141]:
 3    280
-1     42
 0      3
 2      2
 1      2
dtype: int64
In [142]:
import seaborn as sns
import matplotlib.pyplot as plt

data['cl_hdbscan'] = cl_hdbscan.labels_

sns.pairplot(x_vars="Long", 
             y_vars="Lat", 
             hue='cl_hdbscan',
             data=data, 
             height=10)
plt.show()
In [143]:
plt.figure(figsize=(12, 8))
cl_hdbscan.minimum_spanning_tree_.plot(edge_cmap='viridis',
                                      edge_alpha=0.6,
                                      node_size=1,
                                      edge_linewidth=2)
plt.show()

С помощью hdbscan удалось разделить максимум на 5 кластеров, что было близко к моим ассуждениям. Подбирая другие параметры, распределение было намного хуже, это - лучший вариант.

6 задание

В результате выполнения предыдущих пунктов вы должны получить 4 или больше разбиения объектов (по одному на каждый метод). Сравните их между собой, сделайте выводы о сходствах и различиях.

Сравнивая различные методы кластеризации, я нашла несколько сходств и различий.

Что касается сходств, кластеров получилось примерно одно и то же количество(5 штук в hdbscan, 6 штук - в остальных). По правде говоря, я "подгоняла" значение 6 для различных кластеризаций, так как посчитала его оптимально верным. Также для меня достаточно ярко почти во всех методах выделился "островочек" точек, находящийся слева чуть ниже середины (например, выделен зеленым цветом в dbscan'е). Да и вообще, кластеризация в целом везде выглядит в общем похоже.

С другой стороны, естсественно, мы найдем и несколько различий. Во-первых, очевидно, что мы не получили абсолютно идентичную реализацию во всех методах. Во-вторых, время выполнения тоже отличается. Далее см. таблицу ниже.

In [144]:
from sklearn import metrics
from sklearn import datasets
import pandas as pd
from sklearn.cluster import KMeans, AgglomerativeClustering, AffinityPropagation, SpectralClustering

data = datasets.load_digits()
X, y = data.data, data.target

algorithms = []
algorithms.append(KMeans(n_clusters=6, random_state=1))
algorithms.append(AffinityPropagation())
algorithms.append(SpectralClustering(n_clusters=6, random_state=1,
                                     affinity='nearest_neighbors'))
algorithms.append(AgglomerativeClustering(n_clusters=6))

data = []
for algo in algorithms:
    algo.fit(X)
    data.append(({
        'ARI': metrics.adjusted_rand_score(y, algo.labels_),
        'AMI': metrics.adjusted_mutual_info_score(y, algo.labels_),
        'Homogenity': metrics.homogeneity_score(y, algo.labels_),
        'Completeness': metrics.completeness_score(y, algo.labels_),
        'V-measure': metrics.v_measure_score(y, algo.labels_),
        'Silhouette': metrics.silhouette_score(X, algo.labels_)}))

results = pd.DataFrame(data=data, columns=['ARI', 'AMI', 'Homogenity',
                                           'Completeness', 'V-measure', 
                                           'Silhouette'],
                       index=['K-means', 'Affinity', 
                              'Spectral', 'Agglomerative'])

results
/opt/anaconda3/lib/python3.7/site-packages/sklearn/metrics/cluster/supervised.py:746: FutureWarning: The behavior of AMI will change in version 0.22. To match the behavior of 'v_measure_score', AMI will use average_method='arithmetic' by default.
  FutureWarning)
/opt/anaconda3/lib/python3.7/site-packages/sklearn/metrics/cluster/supervised.py:746: FutureWarning: The behavior of AMI will change in version 0.22. To match the behavior of 'v_measure_score', AMI will use average_method='arithmetic' by default.
  FutureWarning)
/opt/anaconda3/lib/python3.7/site-packages/sklearn/metrics/cluster/supervised.py:746: FutureWarning: The behavior of AMI will change in version 0.22. To match the behavior of 'v_measure_score', AMI will use average_method='arithmetic' by default.
  FutureWarning)
/opt/anaconda3/lib/python3.7/site-packages/sklearn/metrics/cluster/supervised.py:746: FutureWarning: The behavior of AMI will change in version 0.22. To match the behavior of 'v_measure_score', AMI will use average_method='arithmetic' by default.
  FutureWarning)
Out[144]:
ARI AMI Homogenity Completeness V-measure Silhouette
K-means 0.430254 0.521175 0.523800 0.695404 0.597525 0.151554
Affinity 0.175174 0.451249 0.958907 0.486901 0.645857 0.115197
Spectral 0.277458 0.522512 0.525191 0.939591 0.673772 0.099819
Agglomerative 0.535147 0.654818 0.656712 0.892511 0.756666 0.137011

7 задание

Выберите одно разбиение, наиболее подходящее на ваш взгляд. Предложите интерпретацию полученным кластерам или покажите, что этого сделать нельзя.

In [233]:
copy = data

data_null = copy

data_null = data_null.loc[data_null['cluster'] != '1']
data_null = data_null.loc[data_null['cluster'] != '2']
data_null = data_null.loc[data_null['cluster'] != '3']
data_null = data_null.loc[data_null['cluster'] != '4']
data_null = data_null.loc[data_null['cluster'] != '5']
      
data_null.head(20)
Out[233]:
Place Climate HousingCost HlthCare Crime Transp Educ Arts Recreat Econ Long Lat Pop cluster
2 Albany,GA 468 7339 618 970 2531 2560 237 859 5250 -84.1580 31.5750 112402 0
5 Alexandria,LA 520 5819 640 727 2444 2972 334 1018 5254 -92.4530 31.3020 135282 0
6 Allentown,Bethlehem,PA-NJ 559 8288 621 514 2881 3144 2333 1117 5097 -75.4405 40.6155 635481 0
8 Altoona,PA 561 6191 432 399 4246 2778 256 1210 4230 -78.3950 40.5150 136621 0
12 Anderson,IN 530 5704 580 878 2865 2469 430 838 3370 -85.6850 40.1670 139336 0
13 Anderson,SC 591 5725 820 975 2707 2772 169 613 4262 -82.6550 34.5100 133235 0
15 Anniston,AL 560 5530 598 1125 3051 2189 268 1165 4730 -85.8270 33.6550 119761 0
16 Appleton-Oshkosh-Neenah,WI 396 7877 833 525 3298 2844 1166 2315 5275 -88.4673 44.1580 291369 0
18 Athens,GA 601 6691 605 933 1866 2646 3546 1001 5193 -83.3830 33.9570 130015 0
21 Augusta,GA-SC 534 6292 1798 872 2523 2915 1047 913 5431 -81.9670 33.4700 345918 0
22 Aurora-Elgin,IL 474 10384 1203 821 3943 2208 3857 1800 5097 -88.2805 41.8935 315607 0
28 Battle-Creek,MI 527 6342 900 1031 4652 2483 354 1648 4008 -85.1820 42.3220 141557 0
30 Beaver-County,PA 586 7866 861 310 2960 2535 1284 1480 3119 -80.3150 40.6930 204441 0
31 Bellingham,WA 772 8329 240 825 3776 2778 1302 3200 4247 -122.4830 48.7630 106701 0
32 Benton-Harbor,MI 566 6761 570 1190 2989 2545 79 1477 3635 -86.4470 42.1050 171276 0
35 Biloxi-Gulfport,MS 584 6458 441 810 2516 2592 679 2106 5801 -88.9695 30.3975 182202 0
38 Bismarck,ND 149 8365 804 413 4303 2686 1211 1630 6019 -100.7780 46.8070 79988 0
39 Bloomington,IN 558 7056 731 657 1746 2873 2152 1990 4829 -86.5280 39.1650 98785 0
45 Brazoria,TX 423 8394 438 768 2391 2718 1506 1512 6020 -95.5700 29.0430 169587 0
46 Bremerton,WA 808 9060 310 651 1670 2544 382 1973 5671 -122.6300 47.5670 147152 0
In [235]:
data_null.tail(20)
Out[235]:
Place Climate HousingCost HlthCare Crime Transp Educ Arts Recreat Econ Long Lat Pop cluster
279 Sheboygan,WI 442 8121 593 450 3458 2557 268 1316 4765 -87.7480 43.7600 100935 0
280 Sherman-Denison,TX 524 5722 394 1035 1922 2652 68 937 6213 -96.5760 33.6950 89796 0
282 Sioux-City,IA-NE 385 6528 846 759 4316 2673 1393 1359 4648 -96.3920 42.4920 117457 0
288 Springfield,MO 544 6343 577 892 3828 2709 1634 1737 5932 -93.2900 37.2200 207704 0
290 State-College,PA 575 8405 612 540 2740 3169 1271 1200 4677 -77.8670 40.7920 112760 0
291 Steubenville-Weirton,OH-WV 542 6578 505 418 1532 2672 147 1460 3744 -80.5970 40.3760 163099 0
297 Terre-Haute,IN 557 5527 453 630 3550 3012 1226 1401 4353 -87.4080 39.4670 137247 0
298 Texarkana,TX-Texarkana,AR 467 5717 343 822 2537 2899 63 669 4772 -94.0525 33.4325 113067 0
304 Tuscaloosa,AL 470 6464 674 1014 4723 2390 1432 1090 4900 -87.5670 33.2050 137541 0
308 Vancouver,WA 768 9015 517 752 3817 2332 1557 1464 4571 -122.6700 45.6250 192227 0
310 Vineland-Millville-Bridgeton,NJ 615 7295 807 1135 4133 2747 2097 1474 5023 -75.0993 39.4377 132866 0
314 Materbury,CT 569 10024 1218 789 2434 2995 318 946 5656 -73.0480 41.4100 204968 0
315 Waterloo-Cedar-Falls,IA 347 7881 925 700 3351 2889 3000 1900 4407 -92.3970 42.5100 162781 0
316 Wausau,WI 308 7642 818 442 3496 2749 761 1654 4300 -89.6400 44.9600 111270 0
318 Wheeling,WV-OH 542 6576 791 308 2450 3002 422 1271 4740 -80.7230 40.0700 185566 0
321 Williamsport,PA 558 7284 860 464 3097 2906 196 726 3288 -77.0030 41.2450 118416 0
325 Yakima,WA 535 6440 317 1106 3731 2491 996 2140 4986 -120.5130 46.5950 172508 0
326 York,PA 540 8371 713 440 2267 2903 1022 842 4946 -76.7280 39.9600 381255 0
327 Youngstown-Warren,OH 570 7021 1097 938 3374 2920 2797 1327 3894 -80.7290 41.1700 531350 0
328 Yuba-City,CA 608 7875 212 1179 2768 2387 122 918 4694 -121.6220 39.1280 101979 0

Анализируя кусочек данного датасета, можно заметить, что особо данные не схожи, так как их очень много. Но сходства можно увидеть, например, в колонках Educ, Econ, Transp.

In [230]:
copy = data

data_one = copy

data_one = data_one.loc[data_one['cluster'] != '0']
data_one = data_one.loc[data_one['cluster'] != '2']
data_one = data_one.loc[data_one['cluster'] != '3']
data_one = data_one.loc[data_one['cluster'] != '4']
data_one = data_one.loc[data_one['cluster'] != '5']

data_one.head(20)
Out[230]:
Place Climate HousingCost HlthCare Crime Transp Educ Arts Recreat Econ Long Lat Pop cluster
19 Atlanta,GA 696 8316 3195 1308 8409 3057 7559 1362 6315 -84.319 33.7630 2138231 1
25 Baltimore,MD 567 9148 3562 1730 7405 3471 9788 2925 5503 -76.617 39.2880 2199531 1
42 Boston,MA 623 11609 5301 1215 6801 3479 21042 3066 6363 -71.058 42.3620 2805911 1
64 Chicago,IL 514 10913 5766 1034 7742 3486 24846 2856 5205 -87.625 41.8830 6060387 1
68 Cleveland,OH 579 9168 3167 1138 7333 2972 12679 3300 4879 -81.700 41.4970 1898825 1
76 Dallas,TX 544 9318 2825 1529 6213 3269 10438 2310 7710 -96.812 32.7770 1957378 1
85 Detroit,MI 536 8525 4142 1587 4808 3064 10389 2483 3904 -83.128 42.4420 4488072 1
134 Houston,TX 424 9760 2467 1499 4626 3271 11073 1825 7464 -95.003 29.8340 2735766 1
178 Los-Angeles,Long-Beach,CA 885 13868 5153 1960 4345 3195 23567 3948 5316 -118.217 33.9165 7477503 1
196 Minneapolis-St.-Paul,MN-WI 293 9559 3934 906 5606 3013 11714 2158 5843 -93.179 44.9650 2137133 1
212 New-York,NY 638 13358 7850 2498 8625 2984 56745 3579 5338 -73.880 40.8490 8274961 1
213 Newark,NJ 601 14220 4106 1461 3514 3362 14224 1818 5690 -74.172 40.7370 1878959 1
233 Philadelphia,PA-NJ 630 8310 5158 1059 5903 3781 17270 1979 5638 -75.163 39.9500 4716818 1
236 Pittsburgh,PA 586 8099 3413 687 5616 3544 11069 2145 5261 -80.008 40.4370 2218870 1
261 St.-Louis,MO-IL 537 7605 2850 1306 7119 3530 8896 2243 5800 -90.193 38.6170 1808621 1
269 San-Francisco,CA 910 17158 3726 1619 8299 3371 14226 4600 6063 -122.417 37.7750 1488871 1
313 Washington,DC-MD-VA 631 13724 4361 1317 8236 3635 21701 1578 6072 -77.033 38.8920 3250822 1
In [231]:
data_one.tail(20)
Out[231]:
Place Climate HousingCost HlthCare Crime Transp Educ Arts Recreat Econ Long Lat Pop cluster
19 Atlanta,GA 696 8316 3195 1308 8409 3057 7559 1362 6315 -84.319 33.7630 2138231 1
25 Baltimore,MD 567 9148 3562 1730 7405 3471 9788 2925 5503 -76.617 39.2880 2199531 1
42 Boston,MA 623 11609 5301 1215 6801 3479 21042 3066 6363 -71.058 42.3620 2805911 1
64 Chicago,IL 514 10913 5766 1034 7742 3486 24846 2856 5205 -87.625 41.8830 6060387 1
68 Cleveland,OH 579 9168 3167 1138 7333 2972 12679 3300 4879 -81.700 41.4970 1898825 1
76 Dallas,TX 544 9318 2825 1529 6213 3269 10438 2310 7710 -96.812 32.7770 1957378 1
85 Detroit,MI 536 8525 4142 1587 4808 3064 10389 2483 3904 -83.128 42.4420 4488072 1
134 Houston,TX 424 9760 2467 1499 4626 3271 11073 1825 7464 -95.003 29.8340 2735766 1
178 Los-Angeles,Long-Beach,CA 885 13868 5153 1960 4345 3195 23567 3948 5316 -118.217 33.9165 7477503 1
196 Minneapolis-St.-Paul,MN-WI 293 9559 3934 906 5606 3013 11714 2158 5843 -93.179 44.9650 2137133 1
212 New-York,NY 638 13358 7850 2498 8625 2984 56745 3579 5338 -73.880 40.8490 8274961 1
213 Newark,NJ 601 14220 4106 1461 3514 3362 14224 1818 5690 -74.172 40.7370 1878959 1
233 Philadelphia,PA-NJ 630 8310 5158 1059 5903 3781 17270 1979 5638 -75.163 39.9500 4716818 1
236 Pittsburgh,PA 586 8099 3413 687 5616 3544 11069 2145 5261 -80.008 40.4370 2218870 1
261 St.-Louis,MO-IL 537 7605 2850 1306 7119 3530 8896 2243 5800 -90.193 38.6170 1808621 1
269 San-Francisco,CA 910 17158 3726 1619 8299 3371 14226 4600 6063 -122.417 37.7750 1488871 1
313 Washington,DC-MD-VA 631 13724 4361 1317 8236 3635 21701 1578 6072 -77.033 38.8920 3250822 1

Похожие значения в признаках Crime, Educ, Econ.

In [228]:
copy = data

data_two = copy

data_two = data_two.loc[data_two['cluster'] != '0']
data_two = data_two.loc[data_two['cluster'] != '1']
data_two = data_two.loc[data_two['cluster'] != '3']
data_two = data_two.loc[data_two['cluster'] != '4']
data_two = data_two.loc[data_two['cluster'] != '5']


data_two.head(20)
Out[228]:
Place Climate HousingCost HlthCare Crime Transp Educ Arts Recreat Econ Long Lat Pop cluster
1 Akron,OH 575 8138 1656 886 4883 2438 5564 2632 4350 -81.5180 41.0850 660328 2
3 Albany-Schenectady-Troy,NY 476 7908 1431 610 6883 3399 4655 1617 5864 -73.7983 42.7327 835880 2
7 Alton,Granite-City,IL 537 6487 965 706 4975 2945 1487 1280 5795 -90.1615 38.7940 268229 2
9 Amarillo,TX 609 6546 669 1073 4902 2852 1235 1109 6241 -101.8490 35.3830 173699 2
17 Asheville,NC 694 6722 1204 566 5086 2990 1391 1542 5196 -82.5570 35.5930 160934 2
26 Bangor,ME 451 7277 780 651 5613 2934 1995 2148 5172 -68.7720 44.8020 83919 2
34 Billings,MT 452 8315 479 810 6285 3008 778 2046 5913 -108.5050 45.7800 108035 2
36 Binghampton,NY 550 8257 1007 415 4529 3052 1599 1722 5614 -75.9130 42.0980 263460 2
37 Birmingham,AL 612 6811 1692 1123 5177 2851 3958 1234 4843 -86.8070 33.5120 883946 2
40 Bloomington-Normal,IL 487 8654 815 673 5889 2854 1470 1605 5863 -88.9900 40.4950 119149 2
41 Boise-City,ID 592 8221 453 880 6575 2391 2385 1672 4633 -116.2180 43.6130 173036 2
54 Burlington,VT 383 9673 1809 494 7146 3323 1741 3357 6726 -73.2070 44.4750 115308 2
57 Cedar-Rapids,IA 434 7774 837 714 5270 2619 904 1501 5009 -91.6730 41.9750 169775 2
58 Champaign-Urbana-Rantoul,IL 525 8627 672 1022 7447 3147 2203 1700 5485 -88.1983 40.1817 168392 2
59 Charleston,SC 569 7402 1463 1495 4207 3164 2993 2561 5153 -79.9300 32.7630 430462 2
60 Charleston,WV 627 7789 708 721 5470 2894 2605 844 5257 -81.6450 38.3680 269595 2
61 Charlotte-Gastonia-Rock-Hill,NC-SC 644 7169 999 1273 6099 3031 4313 1236 5671 -81.0173 35.1370 971391 2
62 Charlottesville,VA 618 9531 1348 756 6041 3489 1422 1704 6055 -78.5070 38.0380 113568 2
65 Chico,CA 603 8587 243 947 4067 3126 1647 1543 5307 -121.8380 39.7320 143851 2
71 Columbia,SC 526 7519 1421 1524 5859 2908 2489 1484 5279 -81.0450 33.9930 410088 2
In [229]:
data_two.tail(20)
Out[229]:
Place Climate HousingCost HlthCare Crime Transp Educ Arts Recreat Econ Long Lat Pop cluster
222 Omaha,NE-IA 440 7128 2559 1008 5806 3069 3787 1977 5853 -96.0080 41.2830 585122 2
223 Orange-County,NY 509 10173 1574 804 3299 2754 6987 1866 5822 -74.4130 41.4530 259603 2
230 Pawtucket-Woonsocket-Attleboro,RI-MA 586 9462 1117 744 4738 3058 480 1513 5154 -71.3953 41.9433 307403 2
237 Pittsfield,MA 482 7807 694 638 3759 3264 228 1420 5483 -73.2530 42.4470 83490 2
238 Portland,ME 483 8100 834 823 5185 2973 2351 3366 6186 -70.2300 43.6780 193831 2
248 Redding,CA 664 8584 274 892 5727 2471 845 2424 4459 -122.4000 40.5820 115715 2
251 Richmond-Petersburg,VA 585 8343 2448 1076 6680 2940 5697 1943 5870 -77.4255 37.3850 761311 2
262 Salem,OR 716 8378 749 1014 4732 3278 691 1873 3835 -123.0280 44.9170 249895 2
276 Scranton-Wilkes-Barre,PA 575 6697 1219 372 3683 3230 1832 1386 4907 -75.7755 41.3275 728796 2
283 Sioux-Falls,SD 276 7983 1041 556 6271 2651 465 1324 5204 -96.7020 43.4950 109435 2
284 South-Bend-Mishawaka,IN 545 5938 830 1038 5634 2874 2672 1819 5056 -86.2150 41.6690 241617 2
285 Spokane,WA 574 6927 497 869 5534 2774 2988 1517 4722 -117.4050 47.6720 341835 2
286 Springfield,IL 524 7882 1877 1225 6172 3078 1983 1536 5384 -89.6480 39.8000 187789 2
287 Springfield,MA 453 8039 710 1212 6159 3525 3466 1514 5289 -72.5880 42.1000 515259 2
293 Syracuse,NY 548 7670 1040 689 6951 3144 5080 2851 4474 -76.1500 43.0520 642971 2
299 Toledo,OH 518 7767 1738 998 5323 2852 4389 1952 4534 -83.5280 41.5910 616864 2
300 Topeka,KS 501 7110 1148 999 5348 2795 1632 1141 5464 -95.6700 39.0520 154916 2
306 Utica-Rome,NY 548 6744 391 400 4592 2970 858 1750 5226 -75.3410 43.1585 320180 2
322 Wilmington,DE-NJ-MD 597 7927 1445 1115 4532 3112 4545 1923 6174 -75.5500 39.7470 523221 2
324 Worcester,MA 562 8715 1805 680 3643 3299 1784 910 5040 -71.7950 42.2720 402918 2

Все те же Educ и Econ, также вижу схожие показатели HousingCost.

In [227]:
copy = data

data_three = copy

data_three = data_three.loc[data_three['cluster'] != '0']
data_three = data_three.loc[data_three['cluster'] != '2']
data_three = data_three.loc[data_three['cluster'] != '1']
data_three = data_three.loc[data_three['cluster'] != '4']
data_three = data_three.loc[data_three['cluster'] != '5']

data_three.head(20)
Out[227]:
Place Climate HousingCost HlthCare Crime Transp Educ Arts Recreat Econ Long Lat Pop cluster
0 Abilene,TX 521 6200 237 923 4031 2757 996 1405 7633 -99.6890 32.55900 110932 3
11 Anchorage,AK 195 12175 601 1223 5091 2414 2346 3000 7668 -127.2016 48.88046 174431 3
20 Atlantic-City,NJ 615 11074 637 1878 3556 2929 621 2711 8107 -74.4380 39.36700 276385 3
23 Austin,TX 435 8831 782 1049 3670 3063 5355 1063 7439 -97.7420 30.28200 536688 3
24 Bakersfield,CA 560 8068 420 1561 3725 2564 1222 1568 6056 -119.0220 35.37500 403089 3
27 Baton-Rouge,LA 427 8083 342 1565 3329 2635 4237 1413 6308 -91.1850 30.45000 494151 3
29 Beaumont-Port-Arthur,TX 423 6288 616 1313 2782 2745 1795 1813 6019 -94.0125 29.99100 375497 3
44 Bradenton,FL 440 8242 333 1093 3805 2712 154 1349 7437 -82.5720 27.49500 148442 3
49 Brockton,MA 575 8263 916 1336 3810 2729 2001 1217 6900 -71.0170 42.08500 182891 3
51 Bryan-College-Station,TX 383 8228 640 1016 2530 2973 2002 1413 8040 -96.3575 30.64400 93588 3
56 Casper,WY 401 9839 345 989 4410 2453 303 1435 6303 -106.3130 42.84700 71856 3
69 Colorado-Springs,CO 526 8509 721 1086 3389 2754 1749 2375 7699 -104.8200 38.83300 309424 3
74 Corpus-Christi,TX 362 6929 458 1335 3626 2840 1992 2037 6690 -97.6210 27.77600 326228 3
81 Daytona-Beach,FL 561 7203 723 1347 4117 2612 809 3967 6592 -81.0230 29.21500 258762 3
94 Enid,OK 461 6829 626 845 2312 2764 215 1200 8268 -97.8750 36.39500 62820 3
106 Fort-Collins-Lover=land,CO 490 9951 731 744 2637 2413 1609 4200 6631 -105.0800 40.49000 149184 3
107 Fort-Lauderdale-Hollywood-Pompano-Beach,FL 572 10810 1252 1536 4186 2734 2027 2455 7136 -80.1373 26.12100 1018200 3
108 Fort-Myers,FL 342 9298 546 787 4583 2729 380 4005 7166 -81.8730 26.64200 205266 3
109 Fort-Pierce,FL 602 8842 527 1422 2143 3154 368 2058 7973 -80.3270 27.44700 151196 3
113 Forth-Arlington,TX 528 7956 1038 1348 4472 2627 6466 2366 6862 -97.1130 32.73700 973138 3
In [225]:
data_three.tail(20)
Out[225]:
Place Climate HousingCost HlthCare Crime Transp Educ Arts Recreat Econ Long Lat Pop cluster
240 Portsmouth-Dover-Rochester,NH-ME 469 9966 596 475 2321 3026 165 1390 8367 -70.8707 43.1900 190938 3
241 Poughkeepsie,NY 488 9981 355 633 4166 2898 785 1670 6746 -73.9300 41.7020 245055 3
266 San-Angelo,TX 488 6321 236 1032 2938 2707 1301 1136 7720 -100.4370 31.4630 84784 3
267 San-Antonio,TX 398 6898 1337 1197 5387 2938 4295 1509 6873 -98.4950 29.4230 1071954 3
274 Sarasota,FL 391 9560 801 939 3742 2626 817 2535 7715 -82.5320 27.3370 202251 3
275 Savannah,GA 542 6896 1084 1614 5958 2456 2262 2237 5591 -81.0930 32.0770 220553 3
281 Shreveport,LA 508 6534 1445 1197 4401 2858 2826 1389 6585 -93.7580 32.4900 333079 3
292 Stockton,CA 625 8474 342 1395 4427 2155 1579 1630 5672 -121.2850 37.9580 347342 3
295 Tallahassee,FL 404 8029 370 1161 5530 2790 2181 1936 6021 -84.2820 30.4450 190220 3
296 Tampa-St.-Petersburg-Clearwater,FL 440 7442 1189 1493 5588 3044 5040 2943 7256 -82.6640 27.9550 1613603 3
302 Tuscon,AZ 589 8548 1259 1400 4397 2685 4889 3131 6147 -110.9680 32.2170 531443 3
303 Tulsa,OK 530 7498 1581 1080 3758 2628 4248 2024 7115 -95.9020 36.1600 657173 3
305 Tyler,TX 500 7298 672 955 3460 3283 404 631 7327 -95.3020 32.3450 128366 3
309 Victoria,TX 336 7143 260 1092 2407 2696 87 1410 7599 -97.0050 28.8050 68807 3
311 Visalia-Tulare-Porterville,CA 543 7778 210 1132 3094 2128 511 2800 5563 -119.2190 36.2043 245738 3
312 Waco,TX 412 6106 538 1166 3018 2867 1141 1248 6259 -97.1420 31.5470 170755 3
317 West-Palm-Beach-Boca-Raton-Delray-Beach,FL 509 10512 375 1783 5201 3224 2888 3772 7992 -80.2177 26.6553 576863 3
319 Wichita,KS 494 7061 806 1164 3933 2981 2987 1508 6036 -97.3370 37.6920 411313 3
320 Wichita-Falls,TX 456 6404 549 1179 2793 2747 599 1126 6805 -98.5130 33.9100 121082 3
323 Wilmington,NC 564 6858 1099 1423 2904 2876 1077 2668 5390 -77.9230 34.2370 103471 3

Educ имеет примерно одно и то же значние, разброс невелик. В принципе, показатель Econ не сильно отличается в каждой из строчек. Да, разброс есть, но не сильно большой.

In [223]:
copy = data

data_four = copy

data_four = data_four.loc[data_four['cluster'] != '0']
data_four = data_four.loc[data_four['cluster'] != '2']
data_four = data_four.loc[data_four['cluster'] != '1']
data_four = data_four.loc[data_four['cluster'] != '3']
data_four = data_four.loc[data_four['cluster'] != '5']

data_four.head(20)
Out[223]:
Place Climate HousingCost HlthCare Crime Transp Educ Arts Recreat Econ Long Lat Pop cluster
4 Albuquerque,NM 659 8393 1853 1483 6558 3026 4496 2612 5727 -106.6500 35.0830 419700 4
10 Anaheim-Santa-Ana,CA 885 16047 2025 983 3954 2843 5632 3156 6220 -117.8890 33.7990 1932709 4
14 Ann-Arbor,MI 546 11014 2508 1067 3433 3346 7559 2288 4579 -83.7500 42.2830 264748 4
33 Bergen-Passaic,NJ 559 14607 2661 857 3511 3653 9304 1918 6016 -74.0590 40.8910 1292970 4
43 Boulder-Longmont,CO 459 11914 962 1088 7108 2587 3663 4012 7127 -105.1930 40.0915 189625 4
47 Bridgeport-Milford,CT 648 13429 2550 943 3197 3029 8368 1913 7197 -73.1265 41.2075 438557 4
52 Buffalo,NY 571 8064 2465 971 5384 3121 8567 2441 5047 -78.8750 42.8870 1015472 4
66 Cincinnati,OH-KY-IN 584 8143 2138 978 5748 2918 9688 2451 5270 -84.5130 39.1000 1401491 4
77 Danbury,CT 569 14420 2350 548 2715 3029 7415 1572 7060 -73.4600 41.3930 170369 4
83 Denver,CO 521 10789 2533 1365 8145 3145 8477 2324 7164 -104.9880 39.7400 1428836 4
96 Eugene-Springfield,OR 741 9370 539 874 5293 3118 2631 3400 3045 -122.9810 43.9520 275226 4
117 Galveston-Texas-City,TX 727 7767 1437 1213 3423 2809 1756 3000 6026 -94.8440 29.3475 195940 4
130 Hartford,CT 516 11652 2521 1279 7120 3628 3616 1790 6307 -72.6750 41.7670 715923 4
132 Honolulu,HI 717 17021 1298 891 5911 2502 7168 3703 5187 -126.0568 31.7365 762565 4
161 Lake-County,IL 514 13282 1237 822 3422 2607 3746 2435 5755 -88.6180 39.6360 440372 4
191 Miami-Hialeah,FL 634 10267 2314 2459 5202 2879 4837 4300 5840 -80.2185 25.6465 1625781 4
192 Middlesex-Somerset,Hunterdon,NJ 559 12135 2589 691 4198 3539 8058 1596 6324 -74.5030 40.5800 886383 4
195 Milwaukee,WI 460 10176 3053 826 4945 3044 8766 2902 4982 -87.9820 43.0330 1397143 4
199 Monmouth-Ocean,NJ 615 11660 2482 819 2690 2787 7563 3544 6154 -74.0750 40.3520 849211 4
206 Nassua-Suffolk,NY 656 11138 3919 566 2119 3234 8640 3705 7371 -73.3750 40.6780 2605813 4
In [224]:
data_four.tail(20)
Out[224]:
Place Climate HousingCost HlthCare Crime Transp Educ Arts Recreat Econ Long Lat Pop cluster
239 Portland,OR 768 9912 1590 1504 5947 3343 5160 2532 4535 -122.3650 45.5470 1105699 4
242 Providence,RI 586 9274 2467 998 5474 3558 6152 2263 5154 -71.4070 41.8170 618514 4
246 Raleigh-Durham,NC 647 8230 3476 981 6544 3455 5730 1606 6405 -78.7650 35.8845 561222 4
249 Reno,NV 535 12449 615 1116 6767 2529 2210 2386 5677 -119.8070 39.5230 193623 4
252 Riverside-San-Bernardino,CA 615 9754 2201 1475 3141 2596 5327 1918 4923 -117.3380 34.0440 1558182 4
255 Rochester,NY 536 8609 1969 894 5165 3582 6956 2659 6304 -77.6080 43.1580 971230 4
257 Sacramento,CA 576 9855 1027 1363 5097 2793 4483 2306 5309 -121.4900 38.5850 1099814 4
263 Salem-Glouster,MA 644 11622 1232 490 3459 2729 3276 2234 6309 -70.7815 42.5755 258175 4
264 Salinas-Seaside-Monterey,CA 843 13838 352 1107 4160 2439 1004 3179 5656 -121.8010 36.6343 290444 4
265 Salt-Lake-City-Ogden,UT 541 9466 1631 969 6228 2340 5528 3900 4942 -111.9350 40.8825 910222 4
268 San-Diego,CA 903 14465 2416 1099 5489 2794 8818 3347 5489 -117.1530 32.7130 1861846 4
270 San-Jose,CA 850 16048 2117 1065 5224 2709 6446 1964 7270 -121.8830 37.3350 1295071 4
271 Santa-Barbara-Santa-Maria-Lompoc,CA 855 15547 532 1026 5662 2719 2684 3300 5821 -120.1960 34.6707 298694 4
272 Santa-Cruz,CA 843 14303 1035 964 5010 2611 3748 1703 5335 -122.0220 36.9720 188141 4
273 Santa-Rosa-Petaluma,CA 732 12931 1052 912 3313 2722 3457 2255 5703 -122.6790 38.3375 299681 4
277 Seattle,WA 808 10183 2715 1170 6634 2710 9577 4800 5901 -122.3300 47.5970 1607469 4
289 Stamford,CT 648 23640 2610 835 3110 3029 7865 1729 6158 -73.5400 41.0530 198854 4
294 Tacoma,WA 808 7770 539 1162 4730 2546 4297 4000 4887 -122.4330 47.2370 485643 4
301 Trenton,NJ 636 10616 1372 1181 4786 3311 5029 1646 5772 -74.7670 40.2250 307863 4
307 Vallejo-Fairfield-Napa,CA 821 10503 1079 964 4153 2498 2962 1559 5819 -122.1940 38.2200 334402 4

Educ имеет примерно одно и то же значние, разброс невелик. В принципе, показатель Econ не сильно отличается в каждой из строчек. Да, разброс есть, но не сильно большой.

In [218]:
copy = data

data_five = copy

data_five = data_five.loc[data_five['cluster'] != '0']
data_five = data_five.loc[data_five['cluster'] != '2']
data_five = data_five.loc[data_five['cluster'] != '1']
data_five = data_five.loc[data_five['cluster'] != '3']
data_five = data_five.loc[data_five['cluster'] != '4']

data_five
Out[218]:
Place Climate HousingCost HlthCare Crime Transp Educ Arts Recreat Econ Long Lat Pop cluster
159 Lafayette,LA 429 8572 548 1030 5268 2305 1772 1734 9702 -92.020 30.225 190231 5
194 Midland,TX 603 8672 97 1166 5310 2416 438 1502 9980 -102.078 31.995 82636 5

Схожие показатели HousingCost, Crime, Transp, Educ, Recreat, Econ. Неудивительно, что здесь нашлось больше схожих признаков, ведь у нас всего 2 строчки, вероятность совпадения выше.

Выводы

У всех кластеров сошлись примерно показатель Educ и Econ, но также это из-за того, что вообще у всех кластеров они схожи, у значений этого признака разброс небольшой. Что же касается разделения на кластеры, они все имеют по одному схожему признаку: где-то Crime, где-то HousingCost и тд. Не знаю точно, но это мое предположение, почему так поделились данные. Про географическое расположение см ниже.

8 задание

Оцените, как полученные кластеры распределены географически. (Бонусное) Провизуализируйте распределение на карте США. Оцените, как полученные кластеры распределены по штатам. Можно ли выделить какую-то зависимость (территориальную или для штатов)?

In [103]:
!pip install folium
Collecting folium
  Downloading folium-0.10.1-py2.py3-none-any.whl (91 kB)
     |████████████████████████████████| 91 kB 637 kB/s eta 0:00:011
Requirement already satisfied: jinja2>=2.9 in /opt/anaconda3/lib/python3.7/site-packages (from folium) (2.10.3)
Requirement already satisfied: requests in /opt/anaconda3/lib/python3.7/site-packages (from folium) (2.22.0)
Requirement already satisfied: numpy in /opt/anaconda3/lib/python3.7/site-packages (from folium) (1.17.2)
Collecting branca>=0.3.0
  Downloading branca-0.4.0-py3-none-any.whl (25 kB)
Requirement already satisfied: MarkupSafe>=0.23 in /opt/anaconda3/lib/python3.7/site-packages (from jinja2>=2.9->folium) (1.1.1)
Requirement already satisfied: idna<2.9,>=2.5 in /opt/anaconda3/lib/python3.7/site-packages (from requests->folium) (2.8)
Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /opt/anaconda3/lib/python3.7/site-packages (from requests->folium) (1.24.2)
Requirement already satisfied: chardet<3.1.0,>=3.0.2 in /opt/anaconda3/lib/python3.7/site-packages (from requests->folium) (3.0.4)
Requirement already satisfied: certifi>=2017.4.17 in /opt/anaconda3/lib/python3.7/site-packages (from requests->folium) (2019.9.11)
Requirement already satisfied: six in /opt/anaconda3/lib/python3.7/site-packages (from branca>=0.3.0->folium) (1.12.0)
Installing collected packages: branca, folium
Successfully installed branca-0.4.0 folium-0.10.1
In [145]:
import folium
In [171]:
data['cluster'] = data_kmeans['cluster']
data
Out[171]:
Place Climate HousingCost HlthCare Crime Transp Educ Arts Recreat Econ Long Lat Pop cluster
0 Abilene,TX 521 6200 237 923 4031 2757 996 1405 7633 -99.6890 32.5590 110932 3
1 Akron,OH 575 8138 1656 886 4883 2438 5564 2632 4350 -81.5180 41.0850 660328 2
2 Albany,GA 468 7339 618 970 2531 2560 237 859 5250 -84.1580 31.5750 112402 0
3 Albany-Schenectady-Troy,NY 476 7908 1431 610 6883 3399 4655 1617 5864 -73.7983 42.7327 835880 2
4 Albuquerque,NM 659 8393 1853 1483 6558 3026 4496 2612 5727 -106.6500 35.0830 419700 4
... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
324 Worcester,MA 562 8715 1805 680 3643 3299 1784 910 5040 -71.7950 42.2720 402918 2
325 Yakima,WA 535 6440 317 1106 3731 2491 996 2140 4986 -120.5130 46.5950 172508 0
326 York,PA 540 8371 713 440 2267 2903 1022 842 4946 -76.7280 39.9600 381255 0
327 Youngstown-Warren,OH 570 7021 1097 938 3374 2920 2797 1327 3894 -80.7290 41.1700 531350 0
328 Yuba-City,CA 608 7875 212 1179 2768 2387 122 918 4694 -121.6220 39.1280 101979 0

329 rows × 14 columns

In [172]:
m = folium.Map(
    location=[45.372, -121.6972],
    zoom_start=4,
    tiles='Stamen Terrain'
)

for i, row in data.iterrows():
    if row['cluster'] == '3':
        color='red'
    elif row['cluster'] == '1':
        color='green'
    elif row['cluster'] == '2':
        color='white'
    elif row['cluster'] == '0':
        color='pink'
    elif row['cluster'] == '4':
        color='blue'
    else: color='orange'
    folium.Marker(location=[row['Lat'], row['Long']], popup=i, icon=folium.Icon(color=color)).add_to(m)
m
Out[172]:

Как можно заметить, большинство данных было собрано с восточной части Соединенных Штатов (преобладает розовый, белый и красный кластеры). Западная половина немного пустует, но ближе к "берегам" там тоже сосредоточены кластеры, в особенности синего цвета.

Красный кластер в оснвном расположился в 4 четверти (юго-восток) и все точки располагаются в нижней части.

В целом зависимости четок не обнаружила, kmeans распределил по своему алгоритму. Мое предположение см. выше.

"